DUT-Info/S3/M3105 (CPOA)

Jean-Michel Bruel
jbruel@gmail.com
version 1.5, 2016-12-14

Points divers

  • Nuit de l’info
  • PTut et Cahier d’Analyse et de Conception
  • Stages

Suivre ces slides sur Internet…​

http://bit.ly/jmb-cpoa
http://iut-blagnac.github.io/cpoa/

Un nouveau diagramme UML très utile

etat1

Les diagrammes d'états-transitions (plus simplement diagramme d’état) d’UML™ décrivent le comportement interne d’un objet à l’aide d’un automate à états finis.

Les notions importantes de ce diagramme :

  • états
  • actions
  • événements déclencheurs

    • signaux
    • invocations de méthode

Transitions

etat2
Événement

Un signal, une invocation de méthode, etc.

Condition

Un booléen

Action

Affectation, invocation de méthode

Exemple de transitions

etat3

Refactoring

On peut remplacer les actions systématiques des transitions entrantes :

etat4

par une transition interne : entry :

etat5

Transitions internes

mdp
entry

permet de spécifier une activité qui s’accomplit quand on entre dans l’état.

exit

permet de spécifier une activité qui s’accomplit quand on sort de l’état.

do

commence dès que l’activité entry est terminée. Lorsque cette activité est terminée, une transition d’achèvement peut être déclenchée. Si une transition se déclenche pendant que l’activité do est en cours, cette dernière est interrompue et l’activité exit de l’état s’exécute.

Conditions

conditions

Exercices

QUESTION
  1. Réalisez un diagramme d’état UML représentant les différents états de l’eau (liquide, solide, gazeux).
  2. Réalisez un diagramme d’état UML représentant les états d’un étudiant de son arrivée en 1ère année à sa sortie de l’IUT en fonction des résultats aux différents examens (uniquement les années, pas les semestres).

Solutions

eau

Solutions

etud

Etats complexes

Un état peut lui-même être doté d’un comportement et donc représenter à lui seul une machine à état. Par exemple :

sousetats

Exercices

QUESTION

Intégrez les semestres aux diagramme précédent (étudiants)

Notion de concurrence

On peut représenter l’évolution de différentes machines de manière concurrente (parallèle). Par exemple :

concurrence

Exercices

QUESTION

Réalisez le diagramme d’état d’une machine à boisson rendant la monnaie.

Solution

monnaie

Le patron Etat

Soit la machine à état suivante :

bonbons

Implémentation intuitive

Implémentation sans switch case
public void insererPiece() {
  if (etat == A_PIECE) {
    System.out.println("Vous ne pouvez plus insérer de pièces");
  } else if (etat == EPUISE) {
    System.out.println("Vous ne pouvez pas insérer de pièce, nous sommes en rupture de stock");
  } else if (etat == VENDU) {
    System.out.println("Veuillez patienter, le bonbon va tomber");
  } else if (etat == SANS_PIECE) {
    etat = A_PIECE;
    System.out.println("Vous avez inséré une pièce");
  }
}

Erreur d’implémentations

  • Ce code n’adhère pas au principe Ouvert-Fermé.
  • Cette conception n’est pas orientée objet.
  • Les transitions ne sont pas explicites. Elles sont enfouies au milieu d’un tas d’instructions conditionnelles.
  • Nous n’avons pas encapsulé ce qui varie.
  • Les ajouts ultérieurs sont susceptibles de provoquer des bugs dans le code.

Une meilleure implémentation

  1. Définir une nouvelle interface Etat qui contiendra une méthode pour chaque action
  2. Implémenter une classe pour chaque Etat. Elles seront responsable du comportement.
  3. Se débarrasser de toutes les instructions conditionnelles et les remplacer par une délégation à la classe adéquate.

Illutration

Etape 1 :

bonbons

bonbons dc

Illustration (suite)

Etape 2

public class EtatSansPiece implements Etat {

  // Va falloir remplir ici...

  public void insererPiece() {
    System.out.println("Vous avez inséré une pièce");
    // changer d'état si besoin

  }
  ...
}

Illustration (suite)

Etape 3

public class Distributeur {

  Etat etat = new EtatSansPiece(); // état initial
  ...
  public void insererPiece() {
    etat.insererPiece(); // on délègue à l'état le soin de réagir
  }
...
}

Illustration (suite)

Etape 4 (enfin, retour sur l’étape 2) : une solution possible…​

public class EtatSansPiece implements Etat {
  Distributeur distributeur; // référence au distributeur qu'on gère

  public EtatSansPiece(Distributeur distributeur) {
    this.distributeur = distributeur;
  }

  public void insererPiece() {
    System.out.println("Vous avez inséré une pièce");
    distributeur.setEtat(distributeur.getEtatAPiece());
  }
  ...
}

Le patron Etat

Etat permet à un objet de modifier son comportement, quand son état interne change. Tout se passe comme si l’objet changeait de classe.

etat
QUESTION

Que pensez-vous de notre solution précédente par rapport à ce diagramme UML?

Solution

L’état possède une référence vers le contexte (Distributeur dans notre exemple).

Figure 1. Une autre implémentation (source : https://sourcemaking.com/design_patterns/state)

Le patron Observer

observer

Motivation

observer illustration

Définition

Observateur définit une relation entre objets de type un-à-plusieurs, de façon que, lorsqu’un objet change d’état, tous ceux qui en dépendent en soient notifiés et soient mis à jour automatiquement.

observateur

Application

Le patron Observer est utilisable dans de nombreuses situations :

  • Quand un concept a deux aspects, l’un dépendant de l’autre. Encapsuler ces aspects dans des objets séparés permet de les utiliser et les laisser évoluer de manière indépendante.
  • Dès que le changement d’un objet entraîne le changement de plusieurs autres.
  • Dès qu’un objet doit en notifier un certain nombre d’autres sans les connaitre.

Observer en Java

Java fournit des classes Observable/Observer pour le patron Observer. La classe java.util.Observable est la classe de base pour les sujets. Ainsi, toute classe qui veut être observée étant cette classe dont voici les caractéristiques :

  • fournit des méthodes pour ajouter/enlever des observateurs
  • fournit des méthodes pour notifier les observateurs
  • une sous-classe concrète doit seulement s’occuper de notifier à chque méthode modifiant l’état des objets (mutators)
  • utilise un vecteur stoquant les références des observateurs

L’interface java.util.Observer correspond aux observateurs qui doivent implémenter cette interface.

La classe java.util.Observable

Voici la liste des méthodes de java.util.Observable :

1 public Observable()
2 public synchronized void addObserver(Observer o)
3 protected synchronized void setChanged()
4 public synchronized void deleteObserver(Observer o)
5 protected synchronized void clearChanged()
6 public synchronized boolean hasChanged()
7 public void notifyObservers(Object arg)
8 public void notifyObservers()

L’interface java.util.Observer

java.util.Observer
 1 /**
 2 * This method is called whenever the observed object is changed. An
 3 * application calls an observable object's notifyObservers method to have all
 4 * the object's observers notified of the change.
 5 *
 6 * Parameters:
 7 * o - the observable object
 8 * arg - an argument passed to the notifyObservers method
 9 */
10 public abstract void update(Observable o, Object arg)

Une implémentation du MVC : les JTable java

JTable

Le principe

TD6 MVC 1

L’architecture

JTable

Le patron Adaptateur

adaptateur

Le problème

On veut pouvoir :

  • utiliser une classe existante, mais dont l’interface ne coïncide pas avec celle escomptée.
  • créer une classe réutilisable qui collabore avec des classes sans relations avec elle et encore inconnues, c’est-à-dire avec des classes qui n’auront pas nécessairement des interfaces compatibles.
  • vous avez besoin d’utiliser plusieurs sous-classes existantes, mais l'adaptation de leur interface par dérivation de chacune d’entre elles est impraticable. Un adaptateur objet peut adapter l’interface de sa classe parente.

    Ce dernier cas ne concerne que le cas "adaptateur d’objet"

Exemple concret : le retour des canards

  • L’existant :
Le Canard
public interface Canard {
  public void cancaner();
  public void voler();
}

public class Colvert implements Canard {
  public void cancaner() {
    System.out.println("Coincoin");
  }
  public void voler() {
    System.out.println("Je vole");
  }
}

Exemple concret : le retour des canards

  • Le "presque canard" :
Le Presque Canard
public interface Dindon {
  public void glouglouter();
  public void voler();
}

public class DindonSauvage implements Dindon {
  public void glouglouter() {
    System.out.println("Glouglou");
  }
  public void voler() {
    System.out.println("Je ne vole pas loin");
  }
}

Exemple concret : le problème

Vous êtes à court d’objets Canard et vous aimeriez utiliser des objets Dindon à la place!

Exemple concret : la solution

Mise en oeuvre du patron Adaptateur
public class AdaptateurDindon implements Canard {
  Dindon dindon;

  ...

  public void cancaner() {
    dindon.glouglouter();
  }

  public void voler() {
    // Adaptation du vol
    for(int i=0; i < 5; i++) {
      dindon.voler();
    }
  }
}

Le patron Adaptateur

Adaptateur (Adaptor) permet de convertir l’interface d’une classe en une autre conformément à l’attente du client. L’Adaptateur permet à des classes de collaborer, alors qu’elles n’auraient pas pu le faire du fait d’interfaces incompatibles.

adapteur

Le patron Adaptateur

adaptor google

Le patron Visiteur

les visiteurs

Le problème

Quelques situations à problème :

  • Une structure d’objets contient beaucoup de classes différentes d’interfaces distinctes, et vous désirez réaliser des opérations sur ces objets qui dépendent de leurs classes concrètes.
  • Il s’agit d’effectuer plusieurs opérations distinctes et sans relation entre elles, sur les objets d’une structure, et ceci en évitant de polluer leurs classes avec ces opérations.
  • Les classes qui définissent la structure objet changent rarement, mais on doit souvent définir de nouvelles opérations sur cette structure.

Illustration

visitor1

Step 1

Définir une interface pour représenter les éléments de la structure.

visitor2

Step 1 (suite)

visitor3
public interface ComputerPart {
   ...
}

Step 2

Anticiper l’utilisation du visiteur.

public interface ComputerPartVisitor {
	...
}
public interface ComputerPart {
   public void accept(ComputerPartVisitor computerPartVisitor);
}

Step 3

Créer les classes concrètes qui implémentent l’interface.

public class Keyboard implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

…​

Step 3 (suite)

public class Computer implements ComputerPart {

   ComputerPart[] parts;

   public Computer(){
      parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
   }


   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      for (int i = 0; i < parts.length; i++) {
         parts[i].accept(computerPartVisitor);
      }
      computerPartVisitor.visit(this);
   }
}

Step 4

Définir l’interface pour représenter le visiteur.

public interface ComputerPartVisitor {
	public void visit(Computer computer);
	public void visit(Mouse mouse);
	public void visit(Keyboard keyboard);
	public void visit(Monitor monitor);
}

Step 5

Créer des visiteurs concrets.

visitor4

Step 5 (suite)

public class DisplayVisitor implements ComputerPartVisitor {

   @Override
   public void visit(Computer computer) {
      System.out.println("Displaying Computer.");
   }

   @Override
   public void visit(Mouse mouse) {
      System.out.println("Displaying Mouse.");
   }

   @Override
   public void visit(Keyboard keyboard) {
      System.out.println("Displaying Keyboard.");
   }

   @Override
   public void visit(Monitor monitor) {
      System.out.println("Displaying Monitor.");
   }
}

Step 6

Utiliser le visiteur DisplayVisitor.

public class VisitorPatternDemo {
   public static void main(String[] args) {

      ComputerPart computer = new Computer();
      computer.accept(new DisplayVisitor());
   }
}

Step 7 (final)

Verify the output.

Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.

Le patron Visiteur

Visiteur (Visitor) permet la représentation d’une opération applicable aux éléments d’une structure d’objet.

Il définit une nouvelle opération, sans qu’il soit nécessaire de modifier la classe des éléments sur lesquels elle agit.

Le patron Visiteur (structure)

visitor dc

Le patron Visiteur (comportement)

visitor seq

Le patron Visiteur (Google)

visitor google

Avantages/Inconvénients

Avantages :

  • Permet d’ajouter des opérations à la structure d’un Composite sans modifier la structure elle-même.
  • L'ajout de nouvelles opérations est relativement facile.
  • Le code des opérations exécutées par le Visiteur est centralisé.

Inconvénients :

  • L’encapsulation des classes du Composite est brisée.
  • Comme une fonction de navigation est impliquée, les modifications de la structure du Composite sont plus difficiles.

Exemples d’utilisation

  • calcul sur un ensemble structuré d’éléments
  • génération de rapports ou de code
  • …​

Exemple concret d’utilisation en Java

Exemple tiré de ce site.
public interface ItemElement {

  public int accept(ShoppingCartVisitor visitor);
}

Exemple concret (suite)

public class Book implements ItemElement {

  private int price;
  private String isbnNumber;

  public Book(int cost, String isbn){
    this.price=cost;
    this.isbnNumber=isbn;
  }

  public int getPrice() {
    return price;
  }

  public String getIsbnNumber() {
    return isbnNumber;
  }

  @Override
  public int accept(ShoppingCartVisitor visitor) {
    return visitor.visit(this);
  }

}

Exemple concret (suite)

public class Fruit implements ItemElement {

  private int pricePerKg;
  private int weight;
  private String name;

  public Fruit(int priceKg, int wt, String nm){
    this.pricePerKg=priceKg;
    this.weight=wt;
    this.name = nm;
  }

  public int getPricePerKg() {
    return pricePerKg;
  }

  public int getWeight() {
    return weight;
  }

  public String getName(){
    return this.name;
  }

  @Override
  public int accept(ShoppingCartVisitor visitor) {
    return visitor.visit(this);
  }
}

Exemple concret (suite)

public interface ShoppingCartVisitor {

  int visit(Book book);
  int visit(Fruit fruit);
}

Exemple concret (suite)

public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {

  @Override
  public int visit(Book book) {
    int cost=0;
    //apply 5$ discount if book price is greater than 50
    if(book.getPrice() > 50){
      cost = book.getPrice()-5;
    } else cost = book.getPrice();
    System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
    return cost;
  }

  @Override
  public int visit(Fruit fruit) {
    int cost = fruit.getPricePerKg()*fruit.getWeight();
    System.out.println(fruit.getName() + " cost = "+cost);
    return cost;
  }
}

Exemple concret (suite)

public class ShoppingCartClient {

  public static void main(String[] args) {
    ItemElement[] items = new ItemElement[]{new Book(20, "1234"),new Book(100, "5678"),
    new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")};

    int total = calculatePrice(items);
    System.out.println("Total Cost = "+total);
  }

  private static int calculatePrice(ItemElement[] items) {
    ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
    int sum=0;
    for(ItemElement item : items){
      sum = sum + item.accept(visitor);
    }
    return sum;
  }

}

Exemple concret (suite)

Book ISBN::1234 cost =20
Book ISBN::5678 cost =95
Banana cost = 20
Apple cost = 25
Total Cost = 160

Le patron proxy

Le problème

On a besoin de références à un objet, qui soient plus créatives et plus sophistiquées qu’un simple pointeur.

Le patron Proxy

Procuration (Proxy) fournit à un tiers un mandataire ou un remplaçant, pour contrôler l’accès à cet objet.

proxy

Le patron Proxy

proxy google

Utilisations

  • Une procuration à distance fournit un représentant local d’un objet situé dans un espace adresse différent.
  • Une procuration virtuelle crée des objets lourds à la demande.
  • Une procuration de protection contrôle l’accès à l’objet original. Les procurations de protection sont utiles quand les objets doivent satisfaire différents droits d’accès.
  • Une référence intelligente est le remplaçant d’un pointeur brut, qui réalise des opérations supplémentaires, lors de l’accès à l’objet. Quelques utilisations typiques sont :

    • décompte du nombre des références faites à un objet réel, de sorte que celui-ci puisse être libéré automatiquement, dés qu’il n’y a plus de références ;
    • charger en mémoire un objet persistant quand il est référencé pour la première fois ;
    • vérifier, avant d’y accéder, que l’objet réel est verrouillé, pour être sûr qu’aucun autre objet ne pourra le changer.

Exemple concret : RMI

Remote Method Invocation

Interface distante
import java.rmi.*;
public interface MonService extends Remote {
  public String direBonjour() throws RemoteException;
}

Exemple concret : RMI (suite)

Le service distant (l’implémentation)
import java.rmi.*;
import java.rmi.server.*;

public class MonServiceImpl extends UnicastRemoteObject implements MonService {
  public String direBonjour() {
    return "Le serveur dit 'Bonjour'";
  }
  public MonServiceImpl() throws RemoteException {}
  public static void main (String[] args) {
    try {
      MonService service = new MonServiceImpl();
      Naming.rebind("BonjourDistant", service);
    } catch(Exception ex) {
      ex.printStackTrace();
    }
  }
}

Exemple concret : RMI (suite)

Utilisation
MonService service =
  (MonService) Naming.lookup("rmi://127.0.0.1/BonjourDistant");
...
service.direBonjour();

Le patron Itérateur

Le problème

On veut pouvoir :

  • pour accéder au contenu d’un objet d’un agrégat sans en révéler la représentation interne ;
  • pour gérer simultanément plusieurs parcours dans des agrégats d’objets ;
  • pour offrir une interface uniforme pour les parcours au travers de diverses structures agrégats (c’est-à-dire, pour permettre l’itération polymorphe).

Le patron Itérateur

Itérateur (Iterator) fournit un moyen d’accès séquentiel aux éléments d’un agrégat d’objets, sans mettre à découvert la représentation interne de celui-ci.

iterateur

Le patron Itérateur

iterateur google

Exemple concret

Itérateur Ruby
# Saluer tout le monde
def say_hi
  if @names.nil?
    puts "..."
  elsif @names.respond_to?("each")
    # @names est une liste de noms : traitons-les uns par uns
    @names.each do |name|
      puts "Hello #{name}!"
    end
  else
    puts "Hello #{@names}!"
  end
end

Le patron Composite

Le problème

On veut pouvoir :

  • représenter des hiérarchies de l’individu.
  • que le client n’ait pas à se préoccuper de la différence entre "combinaisons d’objets" et "objets individuels". Les clients pourront traiter de façon uniforme tous les objets de la structure composite.

Le patron Composite

Composite permet de composer des objets en des structures arborescentes pour représenter des hiérarchies composant/composé. Permet au client de traiter d’une façon unique les objets et les combinaisons d’objets.

composite

Le patron Composite

composite google

Exemple concret

Exemple de Composite Java
import java.util.ArrayList;

interface Graphic {
    public void print();
}

class CompositeGraphic implements Graphic {

  private ArrayList<Graphic> mChildGraphics = new ArrayList<Graphic>();

  public void print() {
    for (Graphic graphic : mChildGraphics) {
      graphic.print();
    }
  }

  public void add(Graphic graphic) {
    mChildGraphics.add(graphic);
  }

  public void remove(Graphic graphic) {
    mChildGraphics.remove(graphic);
  }
}

un "Anti" exemple

Que pensez-vous de cette définition de Composite ?

anti composite
On appelle ces modèles des "Patrons abîmés" (anti-patterns).

Retour sur le refactoring Banque

Le problème

refactoring1

Le problème (suite)

Remplacer tous ces switch cases

continuer = true;
while (continuer) {
  AAB.afficherMenu(monAg);
  choix = lect.next();
  choix = choix.toLowerCase();
  switch (choix) {
    ...
    case "p" :
      System.out.print("Propriétaire -> ");
      nom = lect.next();
      AAB.comptesDUnPropretaire (monAg, nom);
    break;
    ...

Le problème (suite)

  • Afficher une liste séparemment du switch

    //AAB.afficherMenu(monAg);
      System.out.println("Menu de " + ag.getNomAgence() + " (" + ag.getLocAgence() + ")");
      System.out.println("l - Liste des comptes de l'agence");
      ...
      System.out.println("p - voir les comptes d'un Propriétaire (par son nom)");
      ...
      System.out.print("Choix -> ");
    }

  • Tester tous les choix pour actionner la bonne option

    ...
      case "p" :
        System.out.print("Propriétaire -> ");
        nom = lect.next();
        AAB.comptesDUnPropretaire (monAg, nom);
      break;
      ...

Une solution

  • Des listes
  • Des options de menu qui encapsulent l’action à réaliser

Une solution (suite)

public interface ActionList extends Action {

  public String listTitle();
  public int size();

  public boolean addAction(Action ac);
  public boolean removeAction(Action ac);

  public String[] listOfActions() ;

}

Une solution (suite)

Une interface pour les options de menu
public interface Action  {

  public String actionMessage ();
  public void execute(AgenceBancaire ag);
}

Une solution (suite)

Une classe concrète par option de menu
public class Action1 implements Action {

  private String lineMessage;

  ...
  public String actionMessage() {
    return this.lineMessage;
  }

  public void execute(AgenceBancaire ab) {

    ...
    ab.afficher();
  }
}
Utilisation de l’action
action.execute(ab);

Une solution (suite)

Lien entre liste et action
Action a1 = new Action1("Liste des comptes de l'agence");
Action a2 = new Action2("Voir un compte (par son numéro)");
Action a3 = new Action3(...);

ActionList al1 = new ActionListAgenceBancaire("Menu Général");

al1.addAction(a1);
al1.addAction(a2);

Une solution (suite)

Lien entre liste et action : choix dans la liste
public void execute(AgenceBancaire ab) throws Exception {
  ...
  while (true) {
    this.printMenu();

    choice = this.readResponse();
    ...
    this.myMenu.get(choice).execute(ab);
    ...

Une solution (suite)

La liste peut elle-même être une option de menu (une action)!
public interface ActionList extends Action {
}

Pour aller plus loin avec les patrons…​

Partagez votre vocabulaire

  • Dans les réunions de conception (pas nécessairement avec le client)
  • Avec les autres développeurs
  • Dans la documentation de votre architecture
  • Dans les commentaires du code et les conventions de nommage
  • Dans les groupes/blogs de développeurs
  • (pas pendant les exams!)

Ne foncez pas tête baissée

Quelques conseils :

  • Les patterns sont des outils, non des règles.

    ⇒ Rien n’empêche de les modifier et de les adapter à votre problème.

  • Ne visez l’extensibilité que si la question se pose réellement dans la pratique, pas si elle est uniquement hypothétique.
  • Ne vous emballez pas et recherchez la simplicité.

    ⇒ Si vous trouvez une solution plus simple que l’emploi d’un pattern, n’hésitez pas !

  • éliminez ce qui n’est pas vraiment nécessaire.

    ⇒ N’ayez pas peur de supprimer un design pattern inutile de votre conception.

Les autres types de patrons

Il n’y a pas que les 3 types de patrons que l’on a vu :

  • De création
  • Structurels
  • Comportementaux
  • des exemples?

    QUESTION

    Un ou deux exemples de chaque?

Les autres types de patrons (suite)

Il y a par exemple :

  • Les patrons d’architecture
  • Les patrons d’application
  • Les patrons de domaine
  • Les patrons de processus
  • Les patrons d’organisation
  • Les patrons de conception d’interfaces utilisateur

Les anti-patrons

anti patrons

Les anti-patrons

  • Des solutions souvent appliquées à tort à des problèmes récurrents
  • Décrit comment partir d’un problème pour arriver à une mauvaise solution
  • Vous dit pourquoi une mauvaise solution est attrayante
  • Suggère d’autres patrons applicables pouvant fournir de meilleures solutions

Tous les patrons qu’on a pas vu

Il y en a beaucoup :

  • Chaîne de responsabilité
  • Commande
  • Décorateur
  • Façade
  • Interprète
  • Médiateur
  • Mémento
  • Monteur
  • Patron de méthode
  • Poids-mouche
  • Pont
  • Prototype

Principale utilisation des patrons : refactoring!

⇒ Les 2 prochaines semaines vous allez refactorer une application :

  • en binôme
  • en testant
  • en documentant
  • en justifiant
  • en essayant pas à tout prix de caser le plus de patrons "au kilo"

Glossaire et définition

Ces définitions seront enrichies au fur et à mesure des patrons étudiés.

Patrons de création

Singleton

Singleton garantit qu’une classe n’a qu’une seule instance et fournit un point d’accès global à cette instance.

singleton

Patrons de création (suite)

Fabrique

Fabrique (simple) définit une interface pour la création d’un objet, mais en laissant à des sous-classes le choix des classes à instancier (voir aussi Fabrique abstraite).

fabrique

Patrons de création (suite)

Fabrique abstraite

Fabrique (abstraite) fournit une interface pour la création de familles d’objets apparentés ou interdépendants, sans qu’il soit nécessaire de spécifier leurs classes concrètes (voir aussi Fabrique).

fabrique abstraite

Patrons comportementaux

État (Stateuk)

Etat permet à un objet de modifier son comportement, quand son état interne change. Tout se passe comme si l’objet changeait de classe.

etat

Patrons comportementaux (suite)

Itérateur (Iteratoruk)

Itérateur (Iterator) fournit un moyen d’accès séquentiel aux éléments d’un agrégat d’objets, sans mettre à découvert la représentation interne de celui-ci.

iterateur

Patrons comportementaux (suite)

Observateur (Observeruk)

Observateur définit une relation entre objets de type un-à-plusieurs, de façon que, lorsqu’un objet change d’état, tous ceux qui en dépendent en soient notifiés et soient mis à jour automatiquement.

observateur

Patrons comportementaux (suite)

Stratégie (Strategyuk)

Stratégie définit une famille d’algorithmes, encapsule chacun d’eux et les rend interchangeables. Il permet à l’algorithme de varier indépendamment des clients qui l’utilisent.

strategy

Patrons comportementaux (suite)

Visiteur (Visitoruk)

Visiteur (Visitor) permet la représentation d’une opération applicable aux éléments d’une structure d’objet. Il définit une nouvelle opération, sans qu’il soit nécessaire de modifier la classe des éléments sur lesquels elle agit.

visitor dc
visitor seq

Patrons structurels

Adaptateur (Adaptoruk)

Adaptateur (Adaptor) permet de convertir l’interface d’une classe en une autre conformément à l’attente du client. L’Adaptateur permet à des classes de collaborer, alors qu’elles n’auraient pas pu le faire du fait d’interfaces incompatibles.

adapteur

Patrons structurels (suite)

Composite

Composite permet de composer des objets en des structures arborescentes pour représenter des hiérarchies composant/composé. Permet au client de traiter d’une façon unique les objets et les combinaisons d’objets.

composite

Patrons structurels (suite)

Procuration (Proxyuk)

Procuration (Proxy) fournit à un tiers un mandataire ou un remplaçant, pour contrôler l’accès à cet objet.

proxy

Références

  • [GoF] Design Patterns: Elements of reusable object oriented software. 1994.
  • [Freeman04] Design Pattren - Head First. Bert Bates, Eric Freeman, Elisabeth Freeman, Kathy Sierra. O’Reilly, 09/2004.
  • [Freeman05] Tête la première : Design Pattern. Bert Bates, Eric Freeman, Elisabeth Freeman, Kathy Sierra. Editions O’Reilly. 2005.
  • [Cysboy] Apprenez à programmer en Java. Par cysboy. Disponible ici (le 2016-12-14).
  • GOPROD - De bonnes pratiques au service de la conception orientée objets. Disponible ici (le 2016-12-14).
  • [Larman05] Larman, Craig. Applying UML and Patterns – An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd ed.). Prentice Hall. 2005. ISBN 0-13-148906-2.
  • [Meyer88] Meyer, Bertrand. Object-Oriented Software Construction. Prentice Hall. 1988. ISBN 0-13-629049-3.
  • [Martin03] “Principles Of OOD”, Robert C. Martin (“Uncle BOB”), http://butunclebob.com (Last verified 2014-07-17). Note the reference to “the first five principles”, though the acronym is not used in this article. Dates back to at least 2003.

About…​

Document réalisé par Jean-Michel Bruel via Asciidoctor (version 1.5.5) de 'Dan Allen', lui même basé sur AsciiDoc. Pour l’instant ce document est libre d’utilisation et géré par la 'Licence Creative Commons'. Licence Creative Commons licence Creative Commons Paternité - Partage à l'Identique 3.0 non transposé.

/